let container, stats; // domtree插入的位置，当前的状态（FPS、网速、内存占用）
let camera, scene, renderer; // 摄像机，场景，渲染器
let controls; // 相机旋转控制器
let transformControl; // 移动object的控制器，暂时没用到
let light; // 光源

const origin = new THREE.Vector3(-100, -100, -100); // 坐标轴的原点
const driftOrigin = new THREE.Vector3(-100.01, -100.01, -100.01); //偏移的原点，为了解决方格与坐标轴重合的渲染问题
const driftOrigin2 = new THREE.Vector3(-99.99, -99.99, -99.99); // 偏移的原点，渲染两次包住方格阵的线

const guiParams = { // GUI涉及到的初始化值
    light: 250,
    xZoom1: function() {
        xZoom(0.5);
    },
    xZoom2: function() {
        xZoom(2);
    },
    yZoom1: function() {
        yZoom(0.5);
    },
    yZoom2: function() {
        yZoom(2);
    },
    zZoom1: function() {
        zZoom(0.5);
    },
    zZoom2: function() {
        zZoom(2);
    },
    zoom1: function() {
        zoom(0.5);
    },
    zoom2: function() {
        zoom(2);
    },
};

let girdGuiController;

init();
animate();

function init()
{
    // scene
    container = document.getElementById("container");
    scene = new THREE.Scene();
    scene.background = new THREE.Color(0xf0f0f0);

    //camera
    camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 1, 10000); // 透视摄像机
    camera.position.set(0, 0, 300);
    scene.add(camera);

    //light
    scene.add(new THREE.AmbientLight(0xf0f0f0)); // 环境光
    light = new THREE.PointLight(0xffffff, 1, 250, 1); // 点光源，距离为250
    scene.add(light);

    //gird
    var gridHelper = new THREE.Group();

    var xGridHelper = new THREE.GridHelper(200, 10);
    xGridHelper.position.x = -100;
    xGridHelper.rotation.z = Math.PI / 2;
    gridHelper.add(xGridHelper);

    var yGridHelper = new THREE.GridHelper(200, 10);
    yGridHelper.position.y = -100;
    gridHelper.add(yGridHelper);

    var zGridHelper = new THREE.GridHelper(200, 10);
    zGridHelper.position.z = -100;
    zGridHelper.rotation.x = Math.PI / 2;
    gridHelper.add(zGridHelper);

    var xDir = new THREE.Vector3();
    xDir.subVectors(new THREE.Vector3(100, -100, -100), origin).normalize();

    var yDir = new THREE.Vector3();
    yDir.subVectors(new THREE.Vector3(-100, 100, -100), origin).normalize();

    var zDir = new THREE.Vector3();
    zDir.subVectors(new THREE.Vector3(-100, -100, 100), origin).normalize();
    //normalize the direction vector (convert to vector of length 1)
    // xDir.normalize();
    // yDir.normalize();
    // zDir.normalize();

    var xArrowHelper = new THREE.ArrowHelper(xDir, driftOrigin, 220, 0xff0000, 10, 5);
    var yArrowHelper = new THREE.ArrowHelper(yDir, driftOrigin, 220, 0x00ff00, 10, 5);
    var zArrowHelper = new THREE.ArrowHelper(zDir, driftOrigin, 220, 0x0000ff, 10, 5);
    var xArrowHelper2 = new THREE.ArrowHelper(xDir, driftOrigin2, 220, 0xff0000, 0, 0);
    var yArrowHelper2 = new THREE.ArrowHelper(yDir, driftOrigin2, 220, 0x00ff00, 0, 0);
    var zArrowHelper2 = new THREE.ArrowHelper(zDir, driftOrigin2, 220, 0x0000ff, 0, 0);
    
    gridHelper.add(xArrowHelper);
    gridHelper.add(yArrowHelper);
    gridHelper.add(zArrowHelper);
    gridHelper.add(xArrowHelper2);
    gridHelper.add(yArrowHelper2);
    gridHelper.add(zArrowHelper2);

    scene.add(gridHelper);

    //3df init
    reBuild();

    //test
    // (function() {
    //     let geometry = new THREE.BoxBufferGeometry( 100, 100, 100 );
    //     let material = new THREE.MeshBasicMaterial( { color : 0x00ffff,clippingPlanes: [boundPlanes[0]],} );

    //     let mesh = new THREE.Mesh( geometry, material );
    //     mesh.position.y = 100;
    //     scene.add( mesh );
    // })();

    //test clip
    // var helper = new THREE.PlaneHelper( boundPlanes[0], 200, 0x00ffff );
    // scene.add( helper );

    //renderer
    renderer = new THREE.WebGLRenderer({antialias: true});
    renderer.setPixelRatio(window.devicePixelRatio);
    renderer.setSize(window.innerWidth, window.innerHeight);
    renderer.shadowMap.enabled = true;
    renderer.localClippingEnabled = true;
    container.appendChild(renderer.domElement);

    stats = new Stats();
    container.appendChild(stats.dom);

    const gui = new dat.GUI();
    let sceneGui = gui.addFolder("场景");
    let girdGui = sceneGui.addFolder("坐标轴");
    girdGui.add(guiParams, "xZoom1").name("x轴放大");
    girdGui.add(guiParams, "xZoom2").name("x轴缩小");
    girdGui.add(guiParams, "yZoom1").name("y轴放大");
    girdGui.add(guiParams, "yZoom2").name("y轴缩小");
    girdGui.add(guiParams, "zZoom1").name("z轴放大");
    girdGui.add(guiParams, "zZoom2").name("z轴缩小");
    girdGui.add(guiParams, "zoom1").name("集体放大");
    girdGui.add(guiParams, "zoom2").name("集体缩小");
    girdGuiController = {
        xFrom: girdGui.add(bound, "xFrom").name("x起点").onFinishChange(reBuild),
        xTo: girdGui.add(bound, "xTo").name("x终点").onFinishChange(reBuild),
        yFrom: girdGui.add(bound, "yFrom").name("y起点").onFinishChange(reBuild),
        yTo: girdGui.add(bound, "yTo").name("y终点").onFinishChange(reBuild),
        zFrom: girdGui.add(bound, "zFrom").name("z起点").onFinishChange(reBuild),
        zTo: girdGui.add(bound, "zTo").name("z终点").onFinishChange(reBuild),
    };

    let renderGui = gui.addFolder("渲染");

    let functionGui = gui.addFolder("函数");
    functionGui.add(params, "func").name("y=").onFinishChange(reBuild);
    functionGui.add(params, "xResolution", 1, 100).name("x轴分辨率").onFinishChange(reBuild);
    functionGui.add(params, "zResolution", 1, 100).name("z轴分辨率").onFinishChange(reBuild);
    functionGui.add(params, "clippingFromPlanes").name("使用WebGL剪裁").onFinishChange(reBuild);
    functionGui.add(params, "clippingFromCalc").name("在运算时剪裁").onFinishChange(reBuild);
    functionGui.add(params, "drawLine").name("描边").onFinishChange(reBuild);
    let colorGui = functionGui.addFolder("颜色");
    colorGui.addColor(params.materialParams, "color").name("颜色").onFinishChange(reBuild);
    functionGui.add(params, "build").name("重新绘制");

    // Controls
    controls = new THREE.OrbitControls(camera, renderer.domElement);
    controls.damping = 0.2;
    controls.addEventListener("change", render);

    window.addEventListener("resize", onWindowResize, false);
}

function onWindowResize()
{
    camera.aspect = window.innerWidth / window.innerHeight;
    camera.updateProjectionMatrix();

    renderer.setSize(window.innerWidth, window.innerHeight);
}

function animate()
{
    requestAnimationFrame( animate );
    render();
    stats.update();
}

function render()
{
    light.position.copy(camera.position);
    renderer.render( scene, camera );
}